﻿/*
    node 节点对象结构
    {
        id: "T",
        child: [{
            id: "M1"
	    //...和T节点类似
        },
        {
            id: "M2"
	    //...和T节点类似
        }],
        relation: "or",
        event: [{
            id: "c1"
        }]
    }

*/
var cutsetCalculator = {
    __primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47], //素数数组，计算的节点的大小不能超过素数数组的大小
    __primeIndex: 0,
    __rootNode: null,
    findCutset: function (rootNode) {
        this.__init(rootNode);
        var txt = "";
        var cutsetList = [[rootNode]];
        var isFindChild = true;
        while (isFindChild) {
            isFindChild = false;
            var cutsetList_new = [];

            for (var i = 0; i < cutsetList.length; i++) {
                var cutsetTmp = cutsetList[i];
                for (var j = 0; j < cutsetTmp.length; j++) {
                    var n = cutsetTmp[j];

                    if (n.child && n.child.length > 0) {
                        isFindChild = true;
                        if (n.relation == "and") {
                            cutsetTmp.splice(j, 1);
                            for (var k = 0; k < n.child.length; k++) {
                                cutsetTmp.push(n.child[k]);

                                if (n.event && n.event.length > 0) {
                                    for (var l = 0; l < n.event.length; l++) {
                                        cutsetTmp.push(n.event[l]);
                                    }
                                }
                            }
                            cutsetList_new.push(cutsetTmp);
                            break;
                        }
                        else {
                            cutsetTmp.splice(j, 1);
                            for (var k = 0; k < n.child.length; k++) {
                                var tmp = cutsetTmp.slice(0); //复制数组
                                tmp.push(n.child[k]);

                                if (n.event && n.event.length > 0) {
                                    for (var l = 0; l < n.event.length; l++) {
                                        tmp.push(n.event[l]);
                                    }
                                }

                                cutsetList_new.push(tmp);
                            }
                            break;
                        }
                    }
                }

                if (!isFindChild)
                    cutsetList_new.push(cutsetTmp);
            }

            cutsetList = cutsetList_new;
        }

        return cutsetList;
    },
    mergeCutset: function (set) {
        var newSet = this.__calcCutsetPrimeVal(set);
        var mergeSet = [];
        for (var i = 0; i < newSet.length; i++) {
            var isHas = false;
            for (var j = 0; j < mergeSet.length; j++) {
                if (mergeSet.PrimeVal == newSet[i].PrimeVal) {
                    isHas = true;
                    break;
                }
            }

            if (!isHas)
                mergeSet.push(newSet[i]);
        }
        return mergeSet;
    },
    mergeCutsetByPrime: function (mergeSet) {
        var newSet = [];
        for (var i = 0; i < mergeSet.length; i++) {
            var isMod = false;
            for (var j = 0; j < mergeSet.length; j++) {
                if (mergeSet[i].PrimeVal != mergeSet[j].PrimeVal
                    && (mergeSet[i].PrimeVal % mergeSet[j].PrimeVal == 0)) {
                    isMod = true;
                    break;
                }
            }

            if (!isMod)
                newSet.push(mergeSet[i]);
        }
        return newSet;
    },
    __NodeNamePrimeNum: null,
    __init: function (rootNode) {
        this.__rootNode = rootNode;
        this.__primeIndex = 0;
        this.__NodeNamePrimeNum = {};
        this.__initNodes(rootNode)
    },
    __initNodes: function (node) {
        if (this.__NodeNamePrimeNum[node.id]) {
            node.primeNum = this.__NodeNamePrimeNum[node.id];
        }
        else {
            node.primeNum = this.__primes[this.__primeIndex];
            this.__NodeNamePrimeNum[node.id] = node.primeNum;
            this.__primeIndex++;
        }
        if (node.child && node.child.length > 0) {
            for (var i = 0; i < node.child.length; i++) {
                this.__initNodes(node.child[i]);
            }
        }

        if (node.event && node.event.length > 0) {
            for (var i = 0; i < node.event.length; i++) {
                this.__initNodes(node.event[i]);
            }
        }
    },
    __calcCutsetPrimeVal: function (set) {
        var newSet = [];
        for (var i = 0; i < set.length; i++) {
            var newSetItem = [];
            newSetItem.PrimeVal = 1;
            for (var j = 0; j < set[i].length; j++) {
                var isHas = false;
                for (var k = 0; k < newSetItem.length; k++) {
                    if (newSetItem[k].primeNum == set[i][j].primeNum) {
                        isHas = true;
                        break;
                    }
                }

                if (!isHas) {
                    newSetItem.push(set[i][j]);
                    newSetItem.PrimeVal = newSetItem.PrimeVal * set[i][j].primeNum;
                }
            }
            newSet.push(newSetItem);
        }
        return newSet;
    }
};